<?php

namespace app\api\controller;

use think\Request;
use think\Cache;
use think\Config;
use think\Log;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class MiniProgram extends \app\common\controller\Api
{
    protected $noNeedRight = [];
    protected object $client;

    /**
     * @throws GuzzleException
     */
    public function getAccessToken(string $appid, string $secret): string
    {
        $this->client = new Client(['base_uri' => 'https://api.weixin.qq.com/', 'verify' => false]);
        $key = 'access_token';
        
        // 添加时间戳到缓存key，确保定期刷新
        $cacheKey = $key . '_' . date('YmdHi'); // 每分钟变化的key
        
        if (Cache::get($cacheKey)) return Cache::get($cacheKey);
        
        $response = $this->client->get('cgi-bin/token', ['timeout' => 2,
            'query' => ['grant_type' => 'client_credential', 'appid' => $appid, 'secret' => $secret]
        ]);
        if ($response->getStatusCode() !== 200) $this->error('请重新获取', [], 400);
        $data = json_decode($response->getBody());
        Cache::set($cacheKey, $data->access_token, 5400); // 缓存90分钟
        return $data->access_token;
    }

    public function getPromotionCode(Request $request)
    {
        // 添加请求来源调试
        $requestSource = $request->header('User-Agent', 'Unknown') . ' | ' . $request->ip();
        $logMessage = "二维码生成请求来源: " . $requestSource;
        $env    = $this->request->param('env', 'release');

        // 允许的值：develop / trial / release
        if (!in_array($env, ['develop', 'trial', 'release'])) {
            $env = 'release';
        }
        $env = 'release';
        // 获取所有请求参数
        $allParams = $request->param();
        $allPost = $request->post();
        $allGet = $request->get();
        $rawInput = file_get_contents('php://input');
        
        // 将接收到的所有参数输出到响应头
        header('X-All-Params: ' . json_encode($allParams));
        header('X-All-Post: ' . json_encode($allPost));
        header('X-All-Get: ' . json_encode($allGet));
        header('X-Raw-Input: ' . $rawInput);
        header('X-Request-Method: ' . $request->method());
        header('X-Content-Type: ' . $request->header('Content-Type', 'unknown'));
        
        // 输出具体参数到响应头
        $page = $request->post('page', $request->get('page', 'null'));
        $scene = $request->post('scene', $request->get('scene', 'null'));
        $schoolId = $request->post('school_id', $request->get('school_id', 'null'));
        $c = $request->param('c', 'null');
        $i = $request->param('i', 'null');
        $s = $request->param('s', 'null');
        
        header('X-Page-Param: ' . $page);
        header('X-Scene-Param: ' . $scene);
        header('X-SchoolId-Param: ' . $schoolId);
        header('X-C-Param: ' . $c);
        header('X-I-Param: ' . $i);
        header('X-S-Param: ' . $s);
        
        // 记录完整请求信息
        $debugData = [
            'uri' => $request->url(),
            'method' => $request->method(),
            'headers' => $request->header(),
            'params' => $allParams,
            'post' => $allPost,
            'get' => $allGet,
            'raw_input' => $rawInput,
            'request_time' => date('Y-m-d H:i:s'),
            'referer' => $request->header('referer', '无'),
            'origin' => $request->header('origin', '无'),
            'all_request_data' => $request->request(),
            'specific_params' => [
                'page' => $page,
                'scene' => $scene,
                'school_id' => $schoolId,
                'c' => $c,
                'i' => $i,
                's' => $s
            ]
        ];
        
        // 检查是否有school_id参数（多种形式）
        $schoolIdParam = $request->param('school_id');
        $schoolIdPost = $request->post('school_id');
        $schoolIdGet = $request->get('school_id');
        
        if ($schoolIdParam || $schoolIdPost || $schoolIdGet) {
            $logMessage .= " | 发现school_id参数: param=" . $schoolIdParam . ", post=" . $schoolIdPost . ", get=" . $schoolIdGet;
            header('X-Found-SchoolId: true');
            header('X-SchoolId-Param: ' . $schoolIdParam);
            header('X-SchoolId-Post: ' . $schoolIdPost);
            header('X-SchoolId-Get: ' . $schoolIdGet);
        } else {
            header('X-Found-SchoolId: false');
        }
        
        // 检查路由是否被正确解析
        $routeInfo = [
            'current_route' => $request->pathinfo(),
            'dispatch_info' => $request->dispatch(),
            'controller' => $request->controller(),
            'action' => $request->action(),
            'module' => $request->module()
        ];
        
        $debugData['route_info'] = $routeInfo;
        
        // 输出路由信息到响应头
        header('X-Current-Route: ' . $request->pathinfo());
        header('X-Controller: ' . $request->controller());
        header('X-Action: ' . $request->action());
        header('X-Module: ' . $request->module());
        
        // 记录到专门的调试日志文件
        file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", 
            $logMessage . "\n" . json_encode($debugData, JSON_PRETTY_PRINT) . "\n\n", 
            FILE_APPEND | LOCK_EX
        );
        
        // 原有的日志记录
        Log::write($logMessage, 'debug');
        
        // 接收POST参数
        $page = $request->post('page');
        $scene = $request->post('scene');
        
        // 新增：直接接收c,i,s,n参数，用于生成二维码
        $c = $request->post('c');
        $i = $request->post('i');
        $s = $request->post('s');
        $n = $request->post('n');
        
        // 如果提供了c,i,s,n参数，优先使用它们生成scene
        if ($c && $i) {
            // 检查s参数是否包含中文字符
            if (!empty($s) && preg_match('/[\x{4e00}-\x{9fa5}]/u', $s)) {
                // 如果s参数包含中文，只使用c,i参数，不包含中文的s和n
                $scene = $c . ',' . $i . ',,';
                file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "s参数包含中文，使用简化scene: c=" . $c . ", i=" . $i . "\n", FILE_APPEND);
            } else {
                // 正常生成scene
                $scene = $c . ',' . $i . ',' . ($s ?? '') . ',' . ($n ?? '');
                file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "使用直接参数生成scene: c=" . $c . ", i=" . $i . ", s=" . ($s ?? '') . ", n=" . ($n ?? '') . "\n", FILE_APPEND);
            }
        }
        
        // 检查是否意外收到了school_id参数
        $schoolId = $request->post('school_id') ?? $request->get('school_id');
        if ($schoolId) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "警告：意外收到school_id参数: " . $schoolId . "\n", FILE_APPEND);
        }
        
        file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "接收到的page参数: " . ($page ?? 'null') . "\n", FILE_APPEND);
        file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "接收到的scene参数: " . ($scene ?? 'null') . "\n", FILE_APPEND);
        
        // 调试：检查接收到的参数
        if (empty($page) || empty($scene)) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：缺少page或scene参数\n", FILE_APPEND);
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: Missing parameters');
            header('X-QRCode-Page: ' . ($page ?? 'null'));
            header('X-QRCode-Scene: ' . ($scene ?? 'null'));
            
            $this->error('缺少page或scene参数', [], 400);
        }
        
        // 验证scene参数长度，微信限制为32字符
        if (strlen($scene) > 32) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：scene参数过长: " . strlen($scene) . "字符\n", FILE_APPEND);
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: Scene too long');
            header('X-QRCode-Scene-Length: ' . strlen($scene));
            header('X-QRCode-Scene: ' . substr($scene, 0, 50)); // 只显示前50字符
            
            $this->error('scene参数不能超过32字符', [], 400);
        }

        // 按逗号拆 4 段：c,i,s,n（如果之前没有直接设置的话）
        if (!isset($c) || !isset($i)) {
            list($c, $i, $s, $n) = array_pad(explode(',', $scene, 4), 4, '');
        }
        
        // 记录解析的参数
        header('X-Scene-c: ' . $c);
        header('X-Scene-i: ' . $i);
        header('X-Scene-s: ' . urlencode($s ?? ''));
        header('X-Scene-n: ' . urlencode($n ?? ''));
        
        if (!Config::has('wechat.appid') || !Config::has('wechat.secret')) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：微信配置缺失\n", FILE_APPEND);
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: WeChat config missing');
            header('X-QRCode-Page: ' . $page);
            header('X-QRCode-Scene: ' . $scene);
            
            $this->error('需配置appid和secret', [], 400);
        }
        
        try {
            $access_token = $this->getAccessToken(Config::get('wechat.appid'), Config::get('wechat.secret'));
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "成功获取access_token\n", FILE_APPEND);
        } catch (\Exception $e) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：获取access_token失败: " . $e->getMessage() . "\n", FILE_APPEND);
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: Access token error');
            header('X-QRCode-Page: ' . $page);
            header('X-QRCode-Scene: ' . $scene);
            header('X-QRCode-Error: ' . $e->getMessage());
            
            $this->error('获取access_token失败', [], 400);
        }

        // 清理scene参数，移除防缓存参数
        if (strpos($scene, '&t=') !== false) {
            $scene = explode('&t=', $scene)[0];
        }

        // 详细记录二维码生成的所有参数
        $qrcodeParams = [
            'page' => $page,
            'scene' => $scene,
            'scene_length' => strlen($scene),
            'check_path' => false,
            'width' => 280,
            'env_version' => $env,
            'access_token_length' => strlen($access_token),
            'scene_original' => $request->post('scene', $request->get('scene', 'null')),
            'parsed_c' => $c,
            'parsed_i' => $i,
            'parsed_s' => $s ?? '',
            'parsed_n' => $n ?? ''
        ];
        
        // 将二维码参数输出到响应头
        header('X-QRCode-Page: ' . $page);
        header('X-QRCode-Scene: ' . $scene);
        header('X-QRCode-Scene-Length: ' . strlen($scene));
        header('X-QRCode-Timestamp: ' . time());
        header('X-QRCode-Debug: Processing');
        header('X-QRCode-Params: ' . json_encode($qrcodeParams));
        header('X-QRCode-Width: 280');
        header('X-QRCode-Env-Version: ' . $env);
        header('X-QRCode-Check-Path: false');
        
        // 解析scene参数中的具体内容
        if (!empty($scene)) {
            // 尝试解析scene参数，可能包含多个键值对
            $sceneParts = [];
            if (strpos($scene, '&') !== false) {
                // scene参数包含多个部分，如 "school_123&user_456"
                $parts = explode('&', $scene);
                foreach ($parts as $part) {
                    if (strpos($part, '=') !== false) {
                        list($key, $value) = explode('=', $part, 2);
                        $sceneParts[$key] = $value;
                        header('X-Scene-' . ucfirst($key) . ': ' . $value);
                    } else {
                        // 没有等号的简单参数
                        $sceneParts[$part] = $part;
                        header('X-Scene-Part: ' . $part);
                    }
                }
            } else {
                // 单个scene参数
                if (strpos($scene, '=') !== false) {
                    list($key, $value) = explode('=', $scene, 2);
                    header('X-Scene-Single: ' . $key . '=' . $value);
                } else {
                    header('X-Scene-Single: ' . $scene);
                }
            }
            
            header('X-Scene-Parts: ' . json_encode($sceneParts));
            header('X-Scene-Original: ' . $request->post('scene', $request->get('scene', 'null')));
        }
        
        // 记录二维码生成的详细参数到日志
        file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", 
            "二维码生成参数详情:\n" . json_encode($qrcodeParams, JSON_PRETTY_PRINT) . "\n" .
            "Scene参数解析:\n" . json_encode($sceneParts, JSON_PRETTY_PRINT) . "\n\n", 
            FILE_APPEND | LOCK_EX
        );

        try {
            $response = $this->client->post('wxa/getwxacodeunlimit', [
                'query' => ['access_token' => $access_token],
                'json' => [
                    'page'=> $page,
                    'scene'=> $scene,
                    'check_path' => false,
                    'width' => 280,
                    'env_version' => $env
                ],
                'timeout' => 2
            ]);
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "成功调用微信API\n", FILE_APPEND);
        } catch (\Exception $e) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：调用微信API失败: " . $e->getMessage() . "\n", FILE_APPEND);
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: WeChat API error');
            header('X-QRCode-Page: ' . $page);
            header('X-QRCode-Scene: ' . $scene);
            header('X-QRCode-Error: ' . $e->getMessage());
            
            $this->error('调用微信API失败', [], 400);
        }
        
        if ($response->getStatusCode() !== 200) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：微信API返回状态码: " . $response->getStatusCode() . "\n", FILE_APPEND);
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: WeChat API status error');
            header('X-QRCode-Page: ' . $page);
            header('X-QRCode-Scene: ' . $scene);
            header('X-QRCode-Status: ' . $response->getStatusCode());
            
            $this->error('微信API返回异常', [], 400);
        }
        
        $body = $response->getBody();
        $bodyContent = (string)$body;
        
        if(getimagesizefromstring($bodyContent) === false) {
            file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "错误：返回内容不是有效图片\n", FILE_APPEND);
            
            // 尝试解析可能的JSON错误信息
            $jsonData = json_decode($bodyContent, true);
            if (json_last_error() === JSON_ERROR_NONE && isset($jsonData['errcode'])) {
                file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "微信错误码: " . $jsonData['errcode'] . "，错误信息: " . ($jsonData['errmsg'] ?? '未知错误') . "\n", FILE_APPEND);
            }
            
            // 将扫码参数添加到响应头，便于前端调试查看
            header('X-QRCode-Debug: Invalid image response');
            header('X-QRCode-Page: ' . $page);
            header('X-QRCode-Scene: ' . $scene);
            header('X-QRCode-Response-Type: ' . (getimagesizefromstring($bodyContent) === false ? 'not_image' : 'image'));
            
            $this->error('返回内容不是有效图片', [], 400);
        }
        
        file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "二维码生成成功，图片大小: " . strlen($bodyContent) . "字节\n", FILE_APPEND);
        file_put_contents($_SERVER["DOCUMENT_ROOT"]."/../qrcode_full_debug.log", "=== 请求处理完成 ===\n\n", FILE_APPEND);
        
        // 将最终成功的二维码参数添加到响应头，便于前端调试查看
        $finalQrcodeParams = [
            'page' => $page,
            'scene' => $scene,
            'scene_length' => strlen($scene),
            'image_size' => strlen($bodyContent),
            'timestamp' => time(),
            'width' => 280,
            'env_version' => $env,
            'check_path' => 'false',
            'status' => 'success'
        ];
        
        header('X-QRCode-Page: ' . $page);
        header('X-QRCode-Scene: ' . $scene);
        header('X-QRCode-Scene-Length: ' . strlen($scene));
        header('X-QRCode-Timestamp: ' . time());
        header('X-QRCode-Debug: Success');
        header('X-QRCode-Image-Size: ' . strlen($bodyContent));
        header('X-QRCode-Final-Params: ' . json_encode($finalQrcodeParams));
        header('X-QRCode-Status: success');
        header('X-QRCode-Image-Base64-Preview: ' . substr(base64_encode($bodyContent), 0, 100) . '...');
        
        $this->success('获取成功', base64_encode($bodyContent));
    }

}